/*
 * s_smartlock_test.c
 *
 *  Created on: 2019��7��3��
 *      Author: hemin
 */
#include "s_smartlock_test.h"

#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/sysbios/knl/Semaphore.h>

#include <ti/sysbios/BIOS.h>
#include <icall.h>
#include "util.h"

#include "s_debug_msg_handle.h"

#include "h_cc2640r2f_define.h"

#define smartlocktestTaskMd_Task_Stack_Size                 1024
#define smartlocktestTaskMd_Task_PRIORITY                   4

#define SmartLockTest_RandomDataWholen                      10
#define SmartLockTest_SuccessChar1                          0x90
#define SmartLockTest_SuccessChar2                          0x00

#define smartlocktest_BaseTimeLoopPeriod                    500 //ms

#define SmartLockTest_BLE_MSG_Handle                        UTIL_QUEUE_EVENT_ID
#define SmartLockTest_PERIODEvent                           Event_Id_01

#define SmartLockTest_ALLEvent                             SmartLockTest_BLE_MSG_Handle | \
                                                                SmartLockTest_PERIODEvent

#define SmartLockTest_Queue_BLEReady2DIS                    0x0001
#define SmartLockTest_Queue_BLEServiceFound                 0x0002

#define SmartLockTest_Queue_BLEGetNotifyData                0x0003
#define SmartLockTest_Queue_BLEWriteSuccessRsp              0x0004
#define SmartLockTest_Queue_BLEWriteFailedRsp               0x0005
#define SmartLockTest_Queue_BLEDisconnectRsp                0x0006

#define SmartLockTest_Queue_BLEConnectTimeoutRsp            0x0007
#define SmartLockTest_Queue_BLEDisconnectTimeoutRsp         0x0008

// App event passed from profiles.
typedef struct
{
  appEvtHdr_t hdr; // event header
  uint8_t *pData;  // event data
  uint8_t len;
} smartlock_msgt;

typedef struct
{
    unsigned long success;
    unsigned long failed;
    unsigned long unknow;
    unsigned long contimeout;
    unsigned long discontimeout;
}smartlock_rslt;

static smartlock_rslt smartlock_rslt_record;

// Queue object used for app messages
static Queue_Struct appMsg;
static Queue_Handle appMsgQueue;

// Task configuration
Task_Struct smartlocktestTaskMd_Task;

#if defined __TI_COMPILER_VERSION__
#pragma DATA_ALIGN(smartlocktestTaskMd_Task_Stack, 8)
#else
#pragma data_alignment=8
#endif
unsigned char smartlocktestTaskMd_Task_Stack[smartlocktestTaskMd_Task_Stack_Size];

static Event_Handle smartlocktest_eventhandle;
static Event_Struct smartlocktest_eventstruct;

static Clock_Struct timeloopClock;


//void S_SmartLock_Task_EventDone_Notify(void)
//{
//    H_CC2640R2F_UART_Debug("BLE notify post\r\n");
//    Event_post(smartlocktest_eventhandle, SmartLockTest_BLE_MSG_Handle);
//}


static uint8_t S_SmartLock_Task_enqueue(uint8_t event, uint8_t *pData, uint8_t len)
{

    smartlock_msgt *pMsg = ICall_malloc(sizeof(smartlock_msgt));

  // Create dynamic pointer to message.
  if (pMsg)
  {
    pMsg->hdr.event = event;
    pMsg->pData = pData;
    pMsg->len = len;

    // Enqueue the message.
    return Util_enqueueMsg(appMsgQueue, smartlocktest_eventhandle, (uint8_t *)pMsg);
  }

  return FALSE;
}

unsigned char S_SmartLock_BLEReady2Discovery(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEReady2DIS, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}

unsigned char S_SmartLock_BLEConnectTimeout(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEConnectTimeoutRsp, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}

unsigned char S_SmartLock_BLEDisconnectTimeout(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEDisconnectTimeoutRsp, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}


unsigned char S_SmartLock_BLEService_AllReady(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEServiceFound, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}

unsigned char S_SmartLock_BLEService_GetNotifyData(unsigned char *data, unsigned char len)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEGetNotifyData, data, len))
    {
        return FALSE;
    }
    return TRUE;
}

unsigned char S_SmartLock_BLEService_WriteSuccessRspEvent(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEWriteSuccessRsp, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}

unsigned char S_SmartLock_BLEService_WriteFailedRspEvent(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEWriteFailedRsp, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}

unsigned char S_SmartLock_BLEDisconnectedRspEvent(void)
{
    if(S_SmartLock_Task_enqueue(SmartLockTest_Queue_BLEDisconnectRsp, NULL, 0))
    {
        return FALSE;
    }
    return TRUE;
}

//Disconnecting
static unsigned char ble_disconnecting[] = {0x04, S_DBG_MSG_CMD_Devicedisconnect};

// static unsigned char ble_command[] = {0x04, S_DBG_MSG_CMD_connect2Device_byGiven, 0x10, 0x30, 0x00, 0x00, 0x00, 0x10};
// static unsigned char ble_command_withtype[] = {0x04, S_DBG_MSG_CMD_connect2DeviceType_byGiven, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x10};
static unsigned char ble_command_withtype[] = {0x04, S_DBG_MSG_CMD_connect2DeviceType_byGiven, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x48};

//static unsigned char ble_command[] = {0x04, S_DBG_MSG_CMD_connect2Device_byGiven, 0xBA, 0x03, 0x5E, 0x37, 0x4A, 0xB5};
//static unsigned char ble_command[] = {0x04, S_DBG_MSG_CMD_connect2Device_byGiven, 0x99, 0x99, 0x66, 0x66, 0x99, 0x99};
//static unsigned char ble_command[] = {0x04, S_DBG_MSG_CMD_connect2Device_byGiven, 0x10, 0x00, 0x00, 0x00, 0x00, 0x16};

//dual SPP
//static unsigned char ble_command[] = {0x04, S_DBG_MSG_CMD_connect2Device_byGiven, 0x88, 0x1B, 0x99, 0x1B, 0xA2, 0x74};
//My mi band
//static unsigned char ble_command[] = {0x04, S_DBG_MSG_CMD_connect2Device_byGiven, 0x4C, 0x06, 0xCA, 0x3B, 0xF4, 0x8C};


//Get Random data
static unsigned char ble_getrandomdata[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x05, 0x00, 0x84, 0x00, 0x00, 0x08};
//Packdatas:
static unsigned char ble_signedpackdatas_num = 0;
static unsigned char ble_signedpackdata1[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0x00, 0x90, 0x00, 0x00, 0x8C, 0x05, 0x55, 0x55, 0x51, 0x23, 0x00, 0x00, 0x00, 0x11, 0x62, 0x10, 0x30, 0x00, 0x00, 0x00};
static unsigned char ble_signedpackdata2[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0x10, 0x01, 0x10, 0x30, 0x00, 0x00, 0x00, 0x10, 0xA0, 0x9A, 0x22, 0x5D, 0xD0, 0xC4, 0x22, 0x5D, 0x00, 0x0B, 0x6C, 0x6F};
static unsigned char ble_signedpackdata3[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0x63, 0x6B, 0x2E, 0x63, 0x73, 0x63, 0x2E, 0x73, 0x6F, 0x04, 0x55, 0x12, 0xD7, 0x64, 0x18, 0xF5, 0x96, 0xA4, 0x68, 0x54};
static unsigned char ble_signedpackdata4[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0xE2, 0x97, 0xD5, 0x36, 0xC4, 0x3B, 0xCA, 0x67, 0xF0, 0x77, 0x3D, 0xED, 0x12, 0x8A, 0x51, 0x51, 0xCB, 0x86, 0x89, 0x23};
static unsigned char ble_signedpackdata5[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x31, 0x32, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x36, 0x32, 0x46};
static unsigned char ble_signedpackdata6[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x38, 0x30, 0x30, 0x31, 0x30, 0x39, 0x04, 0xBD, 0x21, 0x7E, 0x40};
static unsigned char ble_signedpackdata7[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x14, 0x18, 0xC9, 0x00, 0xF8, 0x11, 0xF3, 0x23, 0xDF, 0xDD, 0x68, 0xEF, 0x8F, 0xEC, 0x32, 0x1E, 0xCB, 0x50, 0xBA, 0x77, 0x6C};
static unsigned char ble_signedpackdata8[] = {0x04, S_DBG_MSG_CMD_doWrite, 0x05, 0x2C, 0x24, 0xCE, 0x2D, 0xCC};

static void s_smartlock_totalresult_dis(void)
{
    H_CC2640R2F_UART_Debug("The rslt s:%ld\tf:%ld\tu:%ld\tct:%ld\tdt:%ld\r\n", smartlock_rslt_record.success, \
                               smartlock_rslt_record.failed, smartlock_rslt_record.unknow, \
                                  smartlock_rslt_record.contimeout, smartlock_rslt_record.discontimeout);

}

static void s_smartlock_notifydatas_handle(unsigned char *data, unsigned char len)
{
    unsigned char rslt = 0U;

    if(ble_signedpackdatas_num == 0)
    {
        if(SmartLockTest_RandomDataWholen != len)
        {
            smartlock_rslt_record.failed++;
            H_CC2640R2F_UART_Debug("Random data whole len is error: %d\r\n", len);
            rslt = 1U;
        }
        else
        {
            if(SmartLockTest_SuccessChar1 != data[8] || SmartLockTest_SuccessChar2 != data[9])
            {
                smartlock_rslt_record.failed++;
                H_CC2640R2F_UART_Debug("Randoms data status error : 0x%02x%02x\r\n", data[8], data[9]);
                rslt = 1U;
            }
            else
            {
                H_CC2640R2F_UART_Debug("The random data is:");
                H_CC2640R2F_UART_Debugprinthex(data, SmartLockTest_RandomDataWholen);
//                H_CC2640R2F_UART_Debug("\r\n");
            }
        }


    }
    else
    {
        H_CC2640R2F_UART_Debug("The signed index is %d, and rslt is :", ble_signedpackdatas_num);
        H_CC2640R2F_UART_Debugprinthex(data, len);
        rslt = 1U;

        if(SmartLockTest_SuccessChar1 != data[0] || SmartLockTest_SuccessChar2 != data[1])
        {
            H_CC2640R2F_UART_Debug("Signed error.\r\n");
            smartlock_rslt_record.failed++;
        }
        else
        {
            H_CC2640R2F_UART_Debug("Signed success.\r\n");
            smartlock_rslt_record.success++;
        }
    }

    if(rslt == 1U)
    {
        ble_signedpackdatas_num = 0U;
        s_smartlock_totalresult_dis();
        H_CC2640R2F_UART_Debug("Disconnecting...\r\n");
        S_Debug_MSG_Handle(ble_disconnecting, sizeof(ble_disconnecting));
    }
    else
    {
//        H_CC2640R2F_UART_Debug("Still disconnecting...\r\n");
//        S_Debug_MSG_Handle(ble_disconnecting, sizeof(ble_disconnecting));
        //Ready to send the first signed pack data
        ble_signedpackdatas_num = 1U;
        S_Debug_MSG_Handle(ble_signedpackdata1, sizeof(ble_signedpackdata1));
    }

}

static void s_smartlock_writesuccessrsp_handle(void)
{
//    H_CC2640R2F_UART_Debug("s_smartlock_writesuccessrsp_handle\r\n");
    switch(ble_signedpackdatas_num)
    {
        case 1:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata2, sizeof(ble_signedpackdata2));
            break;

        case 2:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata3, sizeof(ble_signedpackdata3));
            break;

        case 3:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata4, sizeof(ble_signedpackdata4));
            break;

        case 4:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata5, sizeof(ble_signedpackdata5));
            break;

        case 5:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata6, sizeof(ble_signedpackdata6));
            break;

        case 6:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata7, sizeof(ble_signedpackdata7));
            break;

        case 7:
            ble_signedpackdatas_num++;
            S_Debug_MSG_Handle(ble_signedpackdata8, sizeof(ble_signedpackdata8));
            break;

        default:
            break;
    }
}

static void s_smartlock_writefailedrsp_handle(void)
{
    H_CC2640R2F_UART_Debug("Write failed, disconnecting...\r\n");
    S_Debug_MSG_Handle(ble_disconnecting, sizeof(ble_disconnecting));
}

static void s_smartlock_queuemsg_handle(smartlock_msgt *pMsg)
{
    switch(pMsg->hdr.event)
    {
        case SmartLockTest_Queue_BLEReady2DIS:
            //S_Debug_MSG_Handle(ble_command, sizeof(ble_command));
            S_Debug_MSG_Handle(ble_command_withtype, sizeof(ble_command_withtype));
            break;

        case SmartLockTest_Queue_BLEConnectTimeoutRsp:
            smartlock_rslt_record.contimeout++;
            s_smartlock_totalresult_dis();
            H_CC2640R2F_UART_Debug("Connect time out, re-connected\r\n");
            S_Debug_MSG_Handle(ble_command_withtype, sizeof(ble_command_withtype));
            break;

        case SmartLockTest_Queue_BLEServiceFound:
            S_Debug_MSG_Handle(ble_getrandomdata, sizeof(ble_getrandomdata));
            break;

        case SmartLockTest_Queue_BLEGetNotifyData:
            s_smartlock_notifydatas_handle(pMsg->pData, pMsg->len);
            break;

        case SmartLockTest_Queue_BLEWriteSuccessRsp:
            s_smartlock_writesuccessrsp_handle();
            break;

        case SmartLockTest_Queue_BLEWriteFailedRsp:
            s_smartlock_writefailedrsp_handle();
            break;

        case SmartLockTest_Queue_BLEDisconnectRsp:
            Task_sleep(1000);
//            S_Debug_MSG_Handle(ble_command, sizeof(ble_command));
            S_Debug_MSG_Handle(ble_command_withtype, sizeof(ble_command_withtype));
            break;

        case SmartLockTest_Queue_BLEDisconnectTimeoutRsp:
            H_CC2640R2F_UART_Debug("Connect time out, re-connected\r\n");
            smartlock_rslt_record.discontimeout++;
            s_smartlock_totalresult_dis();
            Task_sleep(1000);
            S_Debug_MSG_Handle(ble_command_withtype, sizeof(ble_command_withtype));
            break;



        default:
            break;

    }
}

static void s_smartlock_task_periodvent_handle(void)
{
    H_CC2640R2F_UART_Debug("Test Period\r\n");
    Util_startClock(&timeloopClock);
}

static void s_smartlock_test_timeloopClock_fun(UArg arg)
{
    Event_post(smartlocktest_eventhandle, arg);
}

static void s_smartlock_task_taskfxn(UArg a0, UArg a1)
{

    Event_Params evParams;
    Event_Params_init(&evParams);
    Event_construct(&smartlocktest_eventstruct, &evParams);
    smartlocktest_eventhandle = \
                    Event_handle(&smartlocktest_eventstruct);

    Util_constructClock(&timeloopClock, s_smartlock_test_timeloopClock_fun,
                            smartlocktest_BaseTimeLoopPeriod, 0, \
                                    false, SmartLockTest_PERIODEvent);

    // Create an RTOS queue for message from profile to be sent to app.
    appMsgQueue = Util_constructQueue(&appMsg);

    smartlock_rslt_record.failed = 0U;
    smartlock_rslt_record.success = 0U;
    smartlock_rslt_record.unknow = 0U;
    smartlock_rslt_record.contimeout = 0U;
    smartlock_rslt_record.discontimeout = 0U;

//    Util_startClock(&timeloopClock);
    for(;;)
    {
        unsigned int events;

        events = Event_pend(smartlocktest_eventhandle, Event_Id_NONE, SmartLockTest_ALLEvent,
                        BIOS_WAIT_FOREVER);

        if(events & SmartLockTest_BLE_MSG_Handle)
        {
            while (!Queue_empty(appMsgQueue))
            {
              smartlock_msgt *pMsg = (smartlock_msgt *)Util_dequeueMsg(appMsgQueue);
              if (pMsg)
              {
                // Process message
                  s_smartlock_queuemsg_handle(pMsg);

                // Free the space from the message
                ICall_free(pMsg);
              }
            }

        }

        if(events & SmartLockTest_PERIODEvent)
        {
            s_smartlock_task_periodvent_handle();
        }

    }
}


void S_SmartLock_Test_Task_Create(void)
{
    Task_Params taskParams;

    // Configure task
    Task_Params_init(&taskParams);
    taskParams.stack = smartlocktestTaskMd_Task_Stack;
    taskParams.stackSize = smartlocktestTaskMd_Task_Stack_Size;
    taskParams.priority = smartlocktestTaskMd_Task_PRIORITY;
    Task_construct(&smartlocktestTaskMd_Task, \
                   s_smartlock_task_taskfxn, &taskParams, NULL);
}





